home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / HyperCuber Source / HyperCuber 2.0 Source.sit / HyperCuber 2.0 Source / Antialias.cp < prev    next >
Text File  |  1994-04-27  |  17KB  |  575 lines

  1. //|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  2. //| This file contains the C++ versions of the antialiasing routines used by HyperCuber
  3. //|________________________________________________________________________________
  4.  
  5.  
  6. #include <FixMath.h>
  7. #include <math.h>
  8.  
  9.  
  10. //============================ Types ============================\\
  11.  
  12. typedef void (*IntensifyProc)(long, long, double);
  13.  
  14.  
  15.  
  16. //============================ Prototypes ============================\\
  17.  
  18. void DrawAntialiasedLine(short x1, short y1, short x2, short y2, RGBColor *color);
  19.  
  20. extern "C" void DrawAntialiasedLineO1asm(long x1, long y1, long x2, long y2, RGBColor *color);
  21. extern "C" void DrawAntialiasedLineO2asm(long x1, long y1, long x2, long y2, RGBColor *color);
  22. extern "C" void DrawAntialiasedLineO3asm(long x1, long y1, long x2, long y2, RGBColor *color);
  23. extern "C" void DrawAntialiasedLineO4asm(long x1, long y1, long x2, long y2, RGBColor *color);
  24.  
  25. void DrawAntialiasedLineO1(long x1, long y1, long x2, long y2, RGBColor *color);
  26. void DrawAntialiasedLineO2(long x1, long y1, long x2, long y2, RGBColor *color);
  27. void DrawAntialiasedLineO3(long x1, long y1, long x2, long y2, RGBColor *color);
  28. void DrawAntialiasedLineO4(long x1, long y1, long x2, long y2, RGBColor *color);
  29.  
  30. void DrawAntialiasedLineO4o(long x1, long y1, long x2, long y2, RGBColor *color);
  31.  
  32. void IntensifyPixel(long x, long y, Fract distance, RGBColor *color);
  33.  
  34. extern Boolean clip_line(long *p1h, long *p1v, long *p2h, long *p2v, Rect *clip_rect);
  35.  
  36.  
  37.  
  38.  
  39. //|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  40. //| Procedure: DrawAntialiasedLine
  41. //|
  42. //| Purpose: draw an antialiased line using Gupta-Sproull's algorithm
  43. //|
  44. //| Parameters: x1,y1,x2,y2:  endpoints of the line
  45. //|             perspective:  TRUE if perspective should be used
  46. //|             left_eye:     TRUE if the left eye view should be drawn;
  47. //|                           FALSE if the right eye view should be drawn.
  48. //|             hyperpane:    the hypercuber pane
  49. //|             pane:         the graphics pane to draw in
  50. //|             color:      color to draw the line
  51. //|____________________________________________________________________
  52.  
  53. void DrawAntialiasedLine(long x1, long y1, long x2, long y2, RGBColor *color,
  54.                                 Rect *clip_rect)
  55. {
  56.  
  57.     if (!clip_line(&x1, &y1, &x2, &y2,            //  Clip line to clip rect
  58.                     clip_rect))
  59.         return;                                    //  Return if line is entirely outside of cliprect
  60.     
  61.     register long xmin;
  62.     register long xmax;
  63.     register long ymin;
  64.     register long ymax;
  65.  
  66.     long dx = (x2 - x1);
  67.     long dy = (y2 - y1);
  68.  
  69.     if (x1 == x2)                        //  Handle vertical lines as special case
  70.         {
  71.         RGBForeColor(color);
  72.         MoveTo(x1, y1);
  73.         LineTo(x2, y2);
  74.         return;
  75.         }
  76.  
  77.     if (x1 < x2)
  78.         {  xmin = x1; xmax = x2;  }    //  Find min and max of x and y
  79.     else
  80.         {  xmin = x2; xmax = x1;  }
  81.  
  82.     if (y1 < y2)
  83.         {  ymin = y1; ymax = y2;  }
  84.     else
  85.         {  ymin = y2; ymax = y1;  }
  86.  
  87.     if ((dx & 0x80000000) == (dy & 0x80000000))    //  If slope > 0, signs are the same
  88.         {
  89.         if (((dx > 0) && (dy > dx)) || ((dx < 0) && (dy < dx)))
  90.             DrawAntialiasedLineO2asm(ymin, xmin, ymax, xmax, color);    //  slope > 1; octant 2
  91.         else
  92.             DrawAntialiasedLineO1asm(xmin, ymin, xmax, ymax, color);    //  slope < 1; octant 1
  93.         }
  94.     else
  95.         {
  96.         if (((dx > 0) && (dy > -dx)) || ((dx < 0) && (dy < -dx)))
  97.             {
  98.             DrawAntialiasedLineO4asm(xmin, -ymax, xmax, -ymin, color);    //  slope > -1; octant 4
  99.             }
  100.         else
  101.             DrawAntialiasedLineO3asm(-ymax, xmin, -ymin, xmax, color);    //  slope < -1; octant 3
  102.         }
  103.  
  104. }    //==== CGraphic::DrawAntialiasedLine () ====\\
  105.  
  106.  
  107. //=============================================================================\\
  108. //=============================================================================\\
  109. //== Below are the C++ versions of the low-level graphics routines.  These   ==\\
  110. //== are provided to make it easier to port these routines.  The routines    ==\\
  111. //== actually used by HyperCuber are written in 68020 Assembly Language, are ==\\
  112. //== in the file "HyperCuber Assembly.asm," and are much faster.  Note that  ==\\
  113. //== the routines below use only integer arithmetic, through the use of the  ==\\
  114. //== Macintosh-specific Fixed and Fract types.  The routines will work on    ==\\
  115. //== other machines (which do not support these types) by using the double   ==\\
  116. //== type.  To make this happen, you have to uncomment the double statements ==\\
  117. //== and delete the Fract statements.  In general, however, floating point   ==\\
  118. //== math is slower than integer math.                                       ==\\
  119. //=============================================================================\\
  120. //=============================================================================\\
  121.  
  122.  
  123. Fract intensity_table2[16] = {    0x40000000, 0x3EF8D2E5, 0x3BEFE0CE, 0x370C77DE,
  124.                                 0x30965F52, 0x29086BDF, 0x214BD33D, 0x1A03A323,
  125.                                 0x1371971C, 0x0DBFD2E9, 0x09086BDF, 0x055831F0,
  126.                                 0x02AF5C0E, 0x0100BE01, 0x002EA30B, 0x00000000   };
  127.  
  128. #if 0
  129.  
  130.  
  131. void IntensifyPixel(long x, long y, Fract distance, RGBColor *color)
  132. {
  133.  
  134. //    double intensity_table[16] = {    1., 0.983937, 0.936516, 0.860136, 0.759178, 0.641139,
  135. //                                     0.520253, 0.406472, 0.303808, 0.214833, 
  136. //                                    0.141139, 0.083508, 0.0419531, 0.0156703, 0.00284649, 0 };
  137.  
  138.     register long red;
  139.     register long green;
  140.     register long blue;
  141.  
  142. //    double intensity = intensity_table[                    //  Get intensity of this point from table
  143. //                    (short) floor(
  144. //                        (fabs(distance)*10 + .5))];
  145.  
  146.     long abs_distance = (distance < 0) ? -distance : distance;        //  Do above without FP arith.
  147.     short index = (((abs_distance / 0x4000) * 10) + 0x8000) >> 16;
  148.     
  149.     Fract fract_intensity = intensity_table[index];
  150.     Fixed intensity = fract_intensity >> 15;            //  This is not really a Fixed; decimal
  151.                                                         //    point is between bits 14 and 15.
  152.  
  153.     RGBColor old_color;
  154.     GetCPixel(x, y, &old_color);                        //  Get previous value of this pixel
  155.     
  156.     red = old_color.red + ((color->red * intensity) >> 15);        //  Merge old and drawing colors
  157.     green = old_color.green + ((color->green * intensity) >> 15);
  158.     blue = old_color.blue + ((color->blue * intensity) >> 15);
  159.  
  160.     RGBColor new_color;
  161.     new_color.red = (red > 0xFFFF) ? 0xFFFF : red;        //  Clip color to 16-bit
  162.     new_color.green = (green > 0xFFFF) ? 0xFFFF : green;
  163.     new_color.blue = (blue > 0xFFFF) ? 0xFFFF : blue;
  164.  
  165.     SetCPixel(x, y, &new_color);                        //  Draw the pixel
  166.  
  167. }    //==== IntensifyPixel() ====\\
  168.  
  169.  
  170.  
  171. void DrawAntialiasedLineO1(long x1, long y1, long x2, long y2, RGBColor *color)
  172. {
  173.  
  174.     long dx, dy;
  175.     register long x;
  176.     register long y;
  177.     register long d;
  178.     long incrE, incrNE, two_v_dx;
  179.     
  180.     dx = x2 - x1;                                //  Find horizontal and vertical distances
  181.     dy = y2 - y1;
  182.     
  183.     d = 2*dy - dx;                                //  Intialize decision variable
  184.     
  185.     incrE = 2*dy;                                //  Increment for d used when moving E
  186.     incrNE = 2*(dy-dx);                            //  Increment for d used when moving NE
  187.     
  188.     two_v_dx = 0;                                //  Numerator of distance from pixel; starts at 0
  189.  
  190. //    invDenom = 1/(2 * sqrt(dx*dx + dy*dy));        //  Denominator of distance from pixel
  191.  
  192.     Fract invDenom =                            //  Do the above command using only int arithmetic
  193.             FracDiv(0x10000,
  194.                 (FracSqrt((dx*dx + dy*dy) * 0x1000) / 16));
  195.     
  196.     Fract two_dx_invDenom = 2*dx*invDenom;        //  Precomputed constant
  197.  
  198.     x = x1;                                        //  Initialize "current point" to start of line
  199.     y = y1;
  200.     
  201.     IntensifyPixel(x, y, 0, color);
  202.     IntensifyPixel(x, y + 1, two_dx_invDenom, color);
  203.     IntensifyPixel(x, y - 1, two_dx_invDenom, color);
  204.         
  205.     while (x < x2)
  206.         {
  207.         
  208.         if (d < 0)
  209.             {
  210.             two_v_dx = d + dx;                    //  Move East
  211.             d += incrE;
  212.             x++;
  213.             }
  214.         else
  215.             {
  216.             two_v_dx = d - dx;                    //  Move NorthEast
  217.             d += incrNE;
  218.             x++;
  219.             y++;
  220.             }
  221.         
  222.         IntensifyPixel(x, y, two_v_dx * invDenom, color);
  223.         IntensifyPixel(x, y + 1, two_dx_invDenom - two_v_dx * invDenom, color);
  224.         IntensifyPixel(x, y - 1, two_dx_invDenom + two_v_dx * invDenom, color);
  225.         
  226.         }    //  end while
  227.  
  228. }    //==== DrawAntialiasedLineO1() ====\\
  229.  
  230.  
  231.  
  232. void DrawAntialiasedLineO2(long x1, long y1, long x2, long y2, RGBColor *color)
  233. {
  234.  
  235.     long dx, dy;
  236.     register long x;
  237.     register long y;
  238.     register long d;
  239.     long incrE, incrNE, two_v_dx;
  240.     
  241.     dx = x2 - x1;                                //  Find horizontal and vertical distances
  242.     dy = y2 - y1;
  243.     
  244.     d = 2*dy - dx;                                //  Intialize decision variable
  245.     
  246.     incrE = 2*dy;                                //  Increment for d used when moving E
  247.     incrNE = 2*(dy-dx);                            //  Increment for d used when moving NE
  248.     
  249.     two_v_dx = 0;                                //  Numerator of distance from pixel; starts at 0
  250.  
  251. //    invDenom = 1/(2 * sqrt(dx*dx + dy*dy));        //  Denominator of distance from pixel
  252.  
  253.     Fract invDenom =                            //  Do the above command using only int arithmetic
  254.             FracDiv(0x10000,
  255.                 (FracSqrt((dx*dx + dy*dy) * 0x1000) / 16));
  256.     
  257.     Fract two_dx_invDenom = 2*dx*invDenom;        //  Precomputed constant
  258.  
  259.     x = x1;                                        //  Initialize "current point" to start of line
  260.     y = y1;
  261.     
  262.     IntensifyPixel(y, x, 0, color);
  263.     IntensifyPixel(y + 1, x, two_dx_invDenom, color);
  264.     IntensifyPixel(y - 1, x, two_dx_invDenom, color);
  265.         
  266.     while (x < x2)
  267.         {
  268.         
  269.         if (d < 0)
  270.             {
  271.             two_v_dx = d + dx;                    //  Move East
  272.             d += incrE;
  273.             x++;
  274.             }
  275.         else
  276.             {
  277.             two_v_dx = d - dx;                    //  Move NorthEast
  278.             d += incrNE;
  279.             x++;
  280.             y++;
  281.             }
  282.  
  283.         IntensifyPixel(y, x, two_v_dx * invDenom, color);
  284.         IntensifyPixel(y + 1, x, two_dx_invDenom - two_v_dx * invDenom, color);
  285.         IntensifyPixel(y - 1, x, two_dx_invDenom + two_v_dx * invDenom, color);
  286.         
  287.         }    //  end while
  288.  
  289. }    //==== DrawAntialiasedLineO2() ====\\
  290.  
  291.  
  292.  
  293. void DrawAntialiasedLineO3(long x1, long y1, long x2, long y2, RGBColor *color)
  294. {
  295.  
  296.     long dx, dy;
  297.     register long x;
  298.     register long y;
  299.     register long d;
  300.     long incrE, incrNE, two_v_dx;
  301.     
  302.     dx = x2 - x1;                                //  Find horizontal and vertical distances
  303.     dy = y2 - y1;
  304.     
  305.     d = 2*dy - dx;                                //  Intialize decision variable
  306.     
  307.     incrE = 2*dy;                                //  Increment for d used when moving E
  308.     incrNE = 2*(dy-dx);                            //  Increment for d used when moving NE
  309.     
  310.     two_v_dx = 0;                                //  Numerator of distance from pixel; starts at 0
  311.  
  312. //    invDenom = 1/(2 * sqrt(dx*dx + dy*dy));        //  Denominator of distance from pixel
  313.  
  314.     Fract invDenom =                            //  Do the above command using only int arithmetic
  315.             FracDiv(0x10000,
  316.                 (FracSqrt((dx*dx + dy*dy) * 0x1000) / 16));
  317.     
  318.     Fract two_dx_invDenom = 2*dx*invDenom;        //  Precomputed constant
  319.  
  320.     x = x1;                                        //  Initialize "current point" to start of line
  321.     y = y1;
  322.  
  323.     IntensifyPixel(y, -x, 0, color);
  324.     IntensifyPixel(y + 1, -x, two_dx_invDenom, color);
  325.     IntensifyPixel(y - 1, -x, two_dx_invDenom, color);
  326.         
  327.     while (x < x2)
  328.         {
  329.         
  330.         if (d < 0)
  331.             {
  332.             two_v_dx = d + dx;                    //  Move East
  333.             d += incrE;
  334.             x++;
  335.             }
  336.         else
  337.             {
  338.             two_v_dx = d - dx;                    //  Move NorthEast
  339.             d += incrNE;
  340.             x++;
  341.             y++;
  342.             }
  343.         
  344.         IntensifyPixel(y, -x, two_v_dx * invDenom, color);
  345.         IntensifyPixel(y + 1, -x, two_dx_invDenom - two_v_dx * invDenom, color);
  346.         IntensifyPixel(y - 1, -x, two_dx_invDenom + two_v_dx * invDenom, color);
  347.  
  348.         }    //  end while
  349.  
  350. }    //==== DrawAntialiasedLineO3() ====\\
  351.  
  352.  
  353.  
  354. void DrawAntialiasedLineO4(long x1, long y1, long x2, long y2, RGBColor *color)
  355. {
  356.  
  357.     long dx, dy;
  358.     register long x;
  359.     register long y;
  360.     register long d;
  361.     long incrE, incrNE, two_v_dx;
  362.     
  363.     dx = x2 - x1;                                //  Find horizontal and vertical distances
  364.     dy = y2 - y1;
  365.     
  366.     d = 2*dy - dx;                                //  Intialize decision variable
  367.     
  368.     incrE = 2*dy;                                //  Increment for d used when moving E
  369.     incrNE = 2*(dy-dx);                            //  Increment for d used when moving NE
  370.     
  371.     two_v_dx = 0;                                //  Numerator of distance from pixel; starts at 0
  372.  
  373. //    invDenom = 1/(2 * sqrt(dx*dx + dy*dy));        //  Denominator of distance from pixel
  374.  
  375.     Fract invDenom =                            //  Do the above command using only int arithmetic
  376.             FracDiv(0x10000,
  377.                 (FracSqrt((dx*dx + dy*dy) * 0x1000) / 16));
  378.     
  379.     Fract two_dx_invDenom = 2*dx*invDenom;        //  Precomputed constant
  380.  
  381.     x = x1;                                        //  Initialize "current point" to start of line
  382.     y = y1;
  383.     
  384.     IntensifyPixel(x, -y, 0, color);
  385.     IntensifyPixel(x, -y - 1, two_dx_invDenom, color);
  386.     IntensifyPixel(x, -y + 1, two_dx_invDenom, color);
  387.         
  388.     while (x < x2)
  389.         {
  390.         
  391.         if (d < 0)
  392.             {
  393.             two_v_dx = d + dx;                    //  Move East
  394.             d += incrE;
  395.             x++;
  396.             }
  397.         else
  398.             {
  399.             two_v_dx = d - dx;                    //  Move NorthEast
  400.             d += incrNE;
  401.             x++;
  402.             y++;
  403.             }
  404.         
  405.         IntensifyPixel(x, -y, two_v_dx * invDenom, color);
  406.         IntensifyPixel(x, -y - 1, two_dx_invDenom - two_v_dx * invDenom, color);
  407.         IntensifyPixel(x, -y + 1, two_dx_invDenom + two_v_dx * invDenom, color);
  408.         
  409.         }    //  end while
  410.  
  411. }    //==== DrawAntialiasedLineO4() ====\\
  412.  
  413.  
  414.  
  415.  
  416. void DrawAntialiasedLineO4o(long x1, long y1, long x2, long y2, RGBColor *color)
  417. {
  418.  
  419.     long dx, dy;
  420.     register long x;
  421.     register long y;
  422.     register long d;
  423.     long incrE, incrNE, two_v_dx;
  424.     
  425.     PixMapHandle pixmap = ((CGrafPtr) thePort)->portPixMap;
  426.     short line_width = (*pixmap)->rowBytes & 0x7FFF;
  427.     unsigned char *base_address = (unsigned char *) (*pixmap)->baseAddr - (*pixmap)->bounds.top*line_width -
  428.                             (*pixmap)->bounds.left;
  429.     register unsigned char *this_pixel = base_address - line_width*y1 + x1;
  430.     
  431.     dx = x2 - x1;                                //  Find horizontal and vertical distances
  432.     dy = y2 - y1;
  433.     
  434.     d = 2*dy - dx;                                //  Intialize decision variable
  435.     
  436.     incrE = 2*dy;                                //  Increment for d used when moving E
  437.     incrNE = 2*(dy-dx);                            //  Increment for d used when moving NE
  438.     
  439.     two_v_dx = 0;                                //  Numerator of distance from pixel; starts at 0
  440.  
  441. //    invDenom = 1/(2 * sqrt(dx*dx + dy*dy));        //  Denominator of distance from pixel
  442.  
  443.     Fract invDenom =                            //  Do the above command using only int arithmetic
  444.             FracDiv(0x10000,
  445.                 (FracSqrt((dx*dx + dy*dy) * 0x1000) / 16));
  446.     
  447.     Fract two_dx_invDenom = 2*dx*invDenom;        //  Precomputed constant
  448.  
  449.     x = x1;                                        //  Initialize "current point" to start of line
  450.     y = y1;
  451.     
  452.     IntensifyPixel(x, -y, 0, color);
  453.     IntensifyPixel(x, -y - 1, two_dx_invDenom, color);
  454.     IntensifyPixel(x, -y + 1, two_dx_invDenom, color);
  455.         
  456.     while (x < x2)
  457.         {
  458.         
  459.         if (d < 0)
  460.             {
  461.             two_v_dx = d + dx;                    //  Move East
  462.             d += incrE;
  463.             this_pixel++;
  464.             }
  465.         else
  466.             {
  467.             two_v_dx = d - dx;                    //  Move NorthEast
  468.             d += incrNE;
  469.             this_pixel -= line_width;
  470.             this_pixel++;
  471.             }
  472.                 
  473.         
  474. //======== Draw the first pixel
  475.         
  476. //        IntensifyPixel(x, -y, two_v_dx * invDenom, color);
  477.  
  478.         RGBColor rgb_black = {0, 0, 0};
  479.         Fract distance, fract_intensity;
  480.         long abs_distance;
  481.         Fixed intensity;                                    //  This is not really a Fixed; decimal
  482.                                                             //    point is between bits 14 and 15.
  483.         RGBColor old_color, new_color;
  484.         long red, green, blue;
  485.         long index;
  486.         
  487.         distance = two_v_dx * invDenom;
  488.         
  489.         abs_distance = (distance < 0) ? -distance : distance;
  490.         index = (((abs_distance / 0x4000) * 10) + 0x8000) >> 16;
  491.     
  492.         fract_intensity = intensity_table[index];
  493.         intensity = fract_intensity >> 15;            
  494.  
  495.         Index2Color(*this_pixel, &old_color);                //  Get previous value of this pixel
  496.         
  497.         old_color = rgb_black;
  498.         
  499.         red = old_color.red + ((color->red * intensity) >> 15);    //  Merge old and drawing colors
  500.         green = old_color.green + ((color->green * intensity) >> 15);
  501.         blue = old_color.blue + ((color->blue * intensity) >> 15);
  502.     
  503.         new_color.red = (red > 0xFFFF) ? 0xFFFF : red;        //  Clip color to 16-bit
  504.         new_color.green = (green > 0xFFFF) ? 0xFFFF : green;
  505.         new_color.blue = (blue > 0xFFFF) ? 0xFFFF : blue;
  506.     
  507.         *this_pixel = Color2Index(&new_color);                //  Draw the pixel
  508.  
  509. //======== Draw the second pixel
  510.         
  511. //        IntensifyPixel(x, -y - 1, two_dx_invDenom - two_v_dx * invDenom, color);
  512.  
  513.         this_pixel -= line_width;
  514.  
  515.         distance = two_dx_invDenom - two_v_dx * invDenom;
  516.         
  517.         abs_distance = (distance < 0) ? -distance : distance;
  518.         index = (((abs_distance / 0x4000) * 10) + 0x8000) >> 16;
  519.     
  520.         fract_intensity = intensity_table[index];
  521.         intensity = fract_intensity >> 15;            
  522.  
  523.         Index2Color(*this_pixel, &old_color);                //  Get previous value of this pixel
  524.         
  525.         old_color = rgb_black;
  526.  
  527.         red = old_color.red + ((color->red * intensity) >> 15);    //  Merge old and drawing colors
  528.         green = old_color.green + ((color->green * intensity) >> 15);
  529.         blue = old_color.blue + ((color->blue * intensity) >> 15);
  530.     
  531.         new_color.red = (red > 0xFFFF) ? 0xFFFF : red;        //  Clip color to 16-bit
  532.         new_color.green = (green > 0xFFFF) ? 0xFFFF : green;
  533.         new_color.blue = (blue > 0xFFFF) ? 0xFFFF : blue;
  534.     
  535.         *this_pixel = Color2Index(&new_color);                //  Draw the pixel
  536.  
  537.         this_pixel += line_width;
  538.  
  539. //======== Draw the third pixel
  540.         
  541.         IntensifyPixel(x, -y + 1, two_dx_invDenom + two_v_dx * invDenom, color);
  542.  
  543.         this_pixel += line_width;
  544.         
  545.         distance = two_dx_invDenom + two_v_dx * invDenom;
  546.         
  547.         abs_distance = (distance < 0) ? -distance : distance;
  548.         index = (((abs_distance / 0x4000) * 10) + 0x8000) >> 16;
  549.     
  550.         fract_intensity = intensity_table[index];
  551.         intensity = fract_intensity >> 15;            
  552.  
  553.         Index2Color(*this_pixel, &old_color);                //  Get previous value of this pixel
  554.  
  555.         old_color = rgb_black;
  556.         
  557.         red = old_color.red + ((color->red * intensity) >> 15);    //  Merge old and drawing colors
  558.         green = old_color.green + ((color->green * intensity) >> 15);
  559.         blue = old_color.blue + ((color->blue * intensity) >> 15);
  560.     
  561.         new_color.red = (red > 0xFFFF) ? 0xFFFF : red;        //  Clip color to 16-bit
  562.         new_color.green = (green > 0xFFFF) ? 0xFFFF : green;
  563.         new_color.blue = (blue > 0xFFFF) ? 0xFFFF : blue;
  564.     
  565.         *this_pixel = Color2Index(&new_color);                //  Draw the pixel
  566.  
  567.         this_pixel -= line_width;
  568.  
  569.         
  570.         }    //  end while
  571.  
  572. }    //==== DrawAntialiasedLineO4o() ====\\
  573.  
  574. #endif
  575.